package com.zeyu.soc.log;

import static spark.Spark.get;
import static spark.Spark.post;
import static spark.Spark.setPort;
import static spark.Spark.staticFileLocation;

import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.ServiceLoader;

import org.eclipse.jetty.util.StringUtil;

import com.zeyu.soc.log.interactive.protocol.CommandRet;
import com.zeyu.soc.log.provider.ClassWrapper;
import com.zeyu.soc.log.provider.FieldWrapper;
import com.zeyu.soc.log.spi.TransformDescriptor;
import com.zeyu.soc.log.spi.annotations.SpiDesc;
import com.zeyu.soc.log.utils.ViewUtils;
import com.zeyu.soc.log.vm.VirtualMachineManager;
import com.zeyu.soc.log.vm.VirtualMachineWrapper;

import spark.Request;
import spark.Response;
import spark.Route;

public class WebServer {

	// ================================================================
	// Constants
	// ================================================================

	/**
	 * 加载所有操作类.
	 */
	private static ServiceLoader<TransformDescriptor> serviceLoader = ServiceLoader.load(TransformDescriptor.class);

	// ================================================================
	// Fields
	// ================================================================

	// 在dialog中 footer不显示
	public static boolean inDialog = false;

	// ================================================================
	// Constructors
	// ================================================================

	// ================================================================
	// Methods from/for super Interfaces or SuperClass
	// ================================================================

	// ================================================================
	// Public or Protected Methods
	// ================================================================

	// ================================================================
	// Getter & Setter
	// ================================================================

	// ================================================================
	// Private Methods
	// ================================================================

	// ================================================================
	// Inner or Anonymous Class
	// ================================================================

	// ================================================================
	// Test Methods
	// ================================================================

	public static void main(String[] args) {

		// Uncomment this if you wan't spark to listen on a port different than 4567.
		int port = 4567;
		if (args != null && args.length > 0) {
			port = Integer.valueOf(args[0]);
		}
		if (args != null && args.length > 1) {
			inDialog = Boolean.valueOf(args[1]);
		}
		setPort(port);

		staticFileLocation("/public");

		// http://localhost:4567/index
		// 首页
		get(new Route("/index") {
			@Override
			public Object handle(Request request, Response response) {
				response.status(200);
				response.type("text/html");

				// rewrite地址
				String rewrite = request.queryParams("rewrite");

				// 输出所有vm
				List<VirtualMachineWrapper> vmList = VirtualMachineManager.getInstance().listVMs();

				List<Map<String, String>> wrappers = new ArrayList<>();
				if (vmList != null && vmList.size() > 0) {
					for (VirtualMachineWrapper vm : vmList) {

						Map<String, String> wrapper = new HashMap<>();
						wrapper.put("id", vm.getId());
						wrapper.put("displayName", vm.getDisplayName());
						wrapper.put("connected", vm.isConnected() + "");
						wrappers.add(wrapper);
					}
				}

				return ViewUtils.renderIndex(wrappers, rewrite);
			}
		});

		// 帮助
		get(new Route("/help") {
			@Override
			public Object handle(Request request, Response response) {
				response.status(200);
				response.type("text/html");

				// rewrite地址
				String rewrite = request.queryParams("rewrite");

				return ViewUtils.renderHelp(rewrite);
			}
		});

		// 操作
		get(new Route("/operator/:id") {
			@Override
			public Object handle(Request request, Response response) {
				response.status(200);
				response.type("text/html");

				String id = request.params("id");
				System.out.println(id);
				String[] ids = id.split("--");
				id = ids[0];
				String operate = ids[1];
				// String operate = request.queryParams("operate");
				System.out.println(operate);

				// rewrite地址
				String rewrite = request.queryParams("rewrite");

				Class<?> operateClass = null;
				try {
					operateClass = Class.forName(operate);
				} catch (ClassNotFoundException e) {
					e.printStackTrace();
				}

				List<FieldWrapper> fieldList = new ArrayList<FieldWrapper>();
				if (null != operateClass) {
					Method[] methods = operateClass.getMethods();
					for (Method method : methods) {
						String methodName = method.getName();
						if (methodName.startsWith("get") && !methodName.equals("getClass")) {
							String fieldName = methodName.substring("get".length());
							String first = fieldName.substring(0, 1).toLowerCase();
							String rest = fieldName.substring(1, fieldName.length());
							String newStr = new StringBuffer(first).append(rest).toString();
							FieldWrapper wrapper = new FieldWrapper();
							wrapper.setFieldName(newStr);
							try {
								SpiDesc descAnnotation = operateClass.getDeclaredField(newStr)
										.getAnnotation(SpiDesc.class);
								if (null != descAnnotation) {
									wrapper.setFieldDesc(descAnnotation.desc());
									wrapper.setCanNull(descAnnotation.canNull());
								} else {
									wrapper.setFieldDesc("该参数无描述");
									wrapper.setCanNull(false);
								}

							} catch (Exception e) {
								e.printStackTrace();
							}
							fieldList.add(wrapper);
						}
					}
				}

				Map<String, Object> wrapper = new HashMap<>();
				wrapper.put("pid", id);
				wrapper.put("operateClassName", operate);

				SpiDesc classDesc = operateClass.getAnnotation(SpiDesc.class);
				if (null != classDesc) {
					wrapper.put("classDesc", classDesc.desc());
				} else {
					wrapper.put("classDesc", "该功能无描述");
				}

				wrapper.put("fields", fieldList);

				return ViewUtils.renderOperator(wrapper, rewrite);
			}
		});

		// 提交操作
		post(new Route("/dooperator") {
			@Override
			public Object handle(Request request, Response response) {
				response.status(200);

				CommandRet ret = new CommandRet();

				String pid = request.queryParams("pid");
				VirtualMachineManager.getInstance().connected(pid, "");

				// rewrite地址
				String rewrite = request.queryParams("rewrite");

				String operateClassName = request.queryParams("operateClassName");
				System.out.println("#####pid=" + pid);
				System.out.println("#####operateClassName=" + operateClassName);
				Class<?> operateClass = null;
				try {
					operateClass = Class.forName(operateClassName);
				} catch (ClassNotFoundException e) {
					e.printStackTrace();
				}

				boolean result = true;
				String message = "";
				ClassWrapper cw = new ClassWrapper();
				if (null != operateClass) {
					Object obj = null;
					try {
						obj = operateClass.newInstance();
					} catch (Exception e) {
						e.printStackTrace();
					}
					Method[] methods = operateClass.getMethods();
					List<FieldWrapper> fieldList = new ArrayList<FieldWrapper>();
					for (Method method : methods) {
						String methodName = method.getName();
						if (methodName.startsWith("set")) {
							String fieldName = methodName.substring("set".length());
							String first = fieldName.substring(0, 1).toLowerCase();
							String rest = fieldName.substring(1, fieldName.length());
							fieldName = new StringBuffer(first).append(rest).toString();

							try {
								System.out.println("fieldName=" + fieldName);
								String parameterValue = request.queryParams(fieldName);
								System.out.println("#####" + parameterValue);
								if (null != parameterValue && !"".equals(parameterValue)) {
									method.invoke(obj, new Object[] { parameterValue });
								}
							} catch (Exception e) {
								e.printStackTrace();
								result = false;
								message = e.getMessage();
								break;
							}
						}
					}
					for (Method method : methods) {
						String methodName = method.getName();

						if (methodName.startsWith("get") && !methodName.equals("getClass")) {
							String fieldName = methodName.substring("get".length());
							String first = fieldName.substring(0, 1).toLowerCase();
							String rest = fieldName.substring(1, fieldName.length());
							String newStr = new StringBuffer(first).append(rest).toString();
							FieldWrapper wrapper = new FieldWrapper();
							wrapper.setFieldName(newStr);
							try {
								wrapper.setValue(method.invoke(obj, new Object[] {}));
							} catch (Exception e) {
								e.printStackTrace();
							}
							fieldList.add(wrapper);
						}
					}

					cw.setClassName(operateClass.getName());
					cw.setFieldWrappers(fieldList);

					System.out.println("###pid=" + pid);
					System.out.println("");
					if (result) {
						ret = VirtualMachineManager.getInstance().sendTransformCommand(pid, (TransformDescriptor) obj);
						if (ret.getRetCode() != 0) {
							result = false;
							message = ret.getRetMsg();
						}
					}
				}

				System.out.println(result);
				System.out.println(message);

				// 注入结果
				response.status(200);
				response.type("text/html");

				Map<String, Object> wrapper = new HashMap<>();
				wrapper.put("result", result);
				wrapper.put("className", operateClassName);
				wrapper.put("message", message);

				wrapper.put("fields", cw);

				return ViewUtils.renderInjectionResult(wrapper, rewrite);
			}
		});

		// 操作选择
		get(new Route("/control/:id") {
			@Override
			public Object handle(Request request, Response response) {
				response.status(200);
				response.type("text/html");

				String id = request.params("id");
				System.out.println(id);

				// rewrite地址
				String rewrite = request.queryParams("rewrite");

				List<Map<String, String>> wrappers = new ArrayList<>();
				for (TransformDescriptor descriptor : serviceLoader) {
					Map<String, String> wrapper = new HashMap<>();
					wrapper.put("id", id);
					wrapper.put("className", descriptor.getClass().getName());
					SpiDesc descAnnotation = descriptor.getClass().getAnnotation(SpiDesc.class);
					if (null != descAnnotation) {
						wrapper.put("classDesc", descAnnotation.desc());
					} else {
						wrapper.put("classDesc", "该功能无描述");
					}
					wrappers.add(wrapper);
				}

				return ViewUtils.renderControl(wrappers, rewrite);
			}
		});

		// 注入列表展示
		get(new Route("/injectionDescriptor/:id") {
			@Override
			public Object handle(Request request, Response response) {
				response.status(200);
				response.type("text/html");

				String pid = request.params("id");
				System.out.println(pid);

				// rewrite地址
				String rewrite = request.queryParams("rewrite");

				List<TransformDescriptor> descs = VirtualMachineManager.getInstance().listTransformDescriptor(pid);

				List<ClassWrapper> wrappers = new ArrayList<ClassWrapper>();

				for (TransformDescriptor desc : descs) {
					ClassWrapper cw = new ClassWrapper();
					List<FieldWrapper> fieldList = new ArrayList<FieldWrapper>();
					Class<?> operateClass = desc.getClass();
					if (null != operateClass) {
						Method[] methods = operateClass.getMethods();
						for (Method method : methods) {
							String methodName = method.getName();
							if (methodName.startsWith("get") && !methodName.equals("getClass")) {
								String fieldName = methodName.substring("get".length());
								String first = fieldName.substring(0, 1).toLowerCase();
								String rest = fieldName.substring(1, fieldName.length());
								String newStr = new StringBuffer(first).append(rest).toString();
								FieldWrapper wrapper = new FieldWrapper();
								wrapper.setFieldName(newStr);
								try {
									wrapper.setValue(method.invoke(desc, new Object[] {}));
								} catch (Exception e) {
									e.printStackTrace();
								}
								fieldList.add(wrapper);
							}
						}
					}
					cw.setClassName(operateClass.getName());
					cw.setFieldWrappers(fieldList);
					wrappers.add(cw);
				}

				return ViewUtils.renderInjectionDescriptor(wrappers, rewrite);
			}
		});

		// 清除注入列表
		get(new Route("/clear/:id") {
			@Override
			public Object handle(Request request, Response response) {
				response.status(200);

				System.out.println(request.params("id"));
				String pid = request.params("id");

				// rewrite地址
				String rewrite = request.queryParams("rewrite");

				VirtualMachineManager.getInstance().disConnected(pid);

				if (StringUtil.isBlank(rewrite)) {
					response.redirect("/index");
				} else {
					response.redirect("/" + rewrite + "/index");
				}

				return "";
			}
		});

		// 根目录跳转到首页
		get(new Route("/") {
			@Override
			public Object handle(Request request, Response response) {

				// rewrite地址
				String rewrite = request.queryParams("rewrite");

				if (StringUtil.isBlank(rewrite)) {
					response.redirect("/index");
				} else {
					response.redirect("/" + rewrite + "/index");
				}

				return "";
			}
		});
	}
}
